package com.ruoyi.web.cp.wechat;


import cn.hutool.http.ContentType;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.reflect.TypeToken;
import lombok.SneakyThrows;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 微信发送消息
 *
 * @author zhangmingliang
 */
public class WeChatMsgSend {
    private CloseableHttpClient httpClient;
    /**
     * 用于提交登陆数据
     */
    private HttpPost httpPost;
    /**
     * 用于获得登录后的页面
     */
    private HttpGet httpGet;

    private static String token;

    private static final Map<Integer, TokenInfo> tokenCache = new ConcurrentHashMap<>();

    public static final String CONTENT_TYPE = "Content-Type";

    @SneakyThrows
    public static String getToken(int appid, boolean isRefresh) {
        TokenInfo tokenInfo = tokenCache.get(appid);
        if (tokenInfo != null && !isRefresh && !tokenInfo.isExpired()) {
            return tokenInfo.getToken();
        }
        WeChatMsgSend swx = new WeChatMsgSend();
        String token = swx.getToken("wwd10c4d16064ab819", getSecret(appid));
        tokenCache.put(appid, new TokenInfo(token, System.currentTimeMillis() + 7200000)); // 有效期2小时
        return token;
    }

    /**
     * 微信授权请求，GET类型，获取授权响应，用于其他方法截取token
     *
     * @param Get_Token_Url
     * @return String 授权响应内容
     * @throws IOException
     */
    protected String toAuth(String Get_Token_Url) throws IOException {
        httpClient = HttpClients.createDefault();
        httpGet = new HttpGet(Get_Token_Url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        String resp;
        try {
            HttpEntity entity = response.getEntity();
            resp = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
        LoggerFactory.getLogger(getClass()).info(" resp:{}", resp);
        return resp;
    }


    /**
     * corpid应用组织编号   corpsecret应用秘钥
     * 获取toAuth(String Get_Token_Url)返回结果中键值对中access_token键的值
     *
     * @param
     */
    public String getToken(String corpid, String corpsecret) throws IOException {
        WeChatMsgSend sw = new WeChatMsgSend();
        WeChatUrlData uData = new WeChatUrlData();
        uData.setGet_Token_Url(corpid, corpsecret);
        String resp = sw.toAuth(uData.getGet_Token_Url());
        System.out.println("resp=====:" + resp);
        try {
            Map<String, Object> map = JSONObject.parseObject(resp, new TypeToken<Map<String, Object>>() {
            }.getType());
            return map.get("access_token").toString();
        } catch (Exception e) {
            return resp;
        }
    }


    /**
     * @return String
     * @Title:创建微信发送请求post数据 touser发送消息接收者    ，msgtype消息类型（文本/图片等），
     * application_id应用编号。
     * 本方法适用于text型微信消息，contentKey和contentValue只能组一对
     */
    public String createpostdata(String touser, String msgtype, int application_id, String contentKey, String contentValue) {
        WeChatData wcd = new WeChatData();
        wcd.setTouser(touser);
        wcd.setAgentid(application_id);
        wcd.setMsgtype(msgtype);
        Map<Object, Object> content = new HashMap<>();
        content.put(contentKey, contentValue);
        wcd.setText(content);
        return JSONObject.toJSONString(wcd);
    }

    /**
     * @return String
     * @Title:创建微信发送请求post数据 touser发送消息接收者    ，msgtype消息类型（文本/图片等），
     * application_id应用编号。
     * media_id文件id，可以调用上传临时素材接口获取
     * 本方法适用于text型微信消息，contentKey和contentValue只能组一对
     */
    public String createpostdata(String touser, String msgtype, int application_id, Object media_id) {
        WeChatData wcd = new WeChatData();
        wcd.setTouser(touser);
        wcd.setAgentid(application_id);
        wcd.setMsgtype(msgtype);
        Map<Object, Object> content = new HashMap<>();
        content.put("media_id", media_id);
        wcd.setFile(content);

        return JSONObject.toJSONString(wcd);
    }


    /**
     * @return String
     * @Title 创建微信发送请求post实体
     * charset消息编码    ，contentType消息体内容类型，
     * url微信消息发送请求地址，data为post数据，token鉴权token
     */
    public String post(String charset, String contentType, String url, String data, String token) throws IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        httpPost = new HttpPost(url + token);
        httpPost.setHeader(CONTENT_TYPE, contentType);
        httpPost.setEntity(new StringEntity(data, charset));
        CloseableHttpResponse response = httpclient.execute(httpPost);
        String resp;
        try {
            HttpEntity entity = response.getEntity();
            resp = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
        LoggerFactory.getLogger(getClass()).info("call [{}], param:{}, resp:{}", url, data, resp);
        return resp;
    }

    public JSONObject uploadMediaByApp(String url, String path) {
        String data = HttpUtil.createPost(url)
                .contentType(ContentType.MULTIPART.toString())
                .form("file", new File(path))
                .execute().body();
        return JSONObject.parseObject(data);
    }


    public static String getSecret(int appid) {
        String secret = null;
        switch (appid) {
            case 1000002:
                //测试
                secret = "eYsa-8jsZShJdEfWKbFNMelxEM3cuLZbw_2Nmv9A4ps";
                break;
            case 1000003:
                //日报
                secret = "NxGvba13Tme8eRR4pfVadHpDfDzCS1zC62gyjKJtKmk";
                break;
            case 1000004:
                //周报
                secret = "Hsc1h_K0237XIbmgT9CiHUJjm1zqDp3GUeiEdk-0pg0";
                break;
            case 1000005:
                //乌龙球
                secret = "ZxZ9-gsMY7_0hq7l_KUo-9mylpItk95xaLriUwVLkTg";
                break;
            case 1000006:
                //红牌及点球
                secret = "xxOC96TalU42gGhBZpLJC82U8iW2YevCO9WN1rBmm3Y";
                break;
            case 1000007:
                //黄牌前换人
                secret = "ZKRds-H4EAz9gKjnOd_tMucd0el6ru9FenPTmEcrnLc";
                break;
            case 1000008:
                //前15分钟进球大于1
                secret = "pXhM4RvAe3eVkiQ20W9uZNTm7uGHRnKlxWC5mgNdRKs";
                break;
            case 1000009:
                //替补进球
                secret = "mHHHUTSD7V4ImS7raxq9mxKETe8HfhdlzN8ongrppLA";
                break;
            case 1000010:
                //前10分种黄牌大于0.5
                secret = "ftAzzuKqvIQNbGcWA-845WH4KNxrzdpp6DNDY9OjddQ";
                break;
            case 1000011:
                //反超
                secret = "0ofAg--Wv25DB4Ao5-QH-ZiPUuGphvFtPWKS-ApjiBo";
                break;
            case 1000012:
                //角球相同
                secret = "zt8I_RNOYn_CAEsUvxN5VkkzkjQq7CRWagvmyftNoZc";
                break;
            case 1000013:
                //半场获取为不同队
                secret = "uFxp-gvW5fGySs9KdsnidMH5SNzfkulC_zj2MVcnbvo";
                break;
            case 1000014:
                //半场获取为不同队
                secret = "1OMfiL-xdWXNO1y2N-Rf8CGIhmpWR21pYyqa4I_HR5U";
                break;
            case 1000015:
                secret = "Kvifm2v8q0NiBe-BEYtkHW1IChgjvNlxTF3lsR7RFPs";
                break;
            case 1000016:
                secret = "I8S1ZwBP5mgeLIMLFKEGM1WN88ZkuyjcATD2CfFCXSU";
                break;
            case 1000017:
                secret = "gIjEgoUZkX0av7LtGEtj84k2RvKy4vGBSaAJRm7_2iU";
                break;
            case 1000018:
                secret = "7ZwAAoCp9oekGLJNWPUSgSX7Stu44luEDtNNAqKPATc";
                break;
            case 1000019:
                secret = "lXk6WVvBvXzmiQOvgAzGkQgrn5hpUNT-Ne6doCQntKE";
                break;
        }
        return secret;
    }

    static class TokenInfo {
        private final String token;
        private final long expireTime;

        public TokenInfo(String token, long expireTime) {
            this.token = token;
            this.expireTime = expireTime;
        }

        public String getToken() {
            return token;
        }

        public boolean isExpired() {
            return System.currentTimeMillis() >= expireTime;
        }
    }

}